/* See COPYRIGHT for copyright information. */

#include <inc/mmu.h>
#include <inc/memlayout.h>
#include <inc/trap.h>

#include <kern/picirq.h>


###################################################################
# exceptions/interrupts
###################################################################

/* The TRAPHANDLER macro defines a globally-visible function for handling
 * a trap.  It pushes a trap number onto the stack, then jumps to _alltraps.
 * Use TRAPHANDLER for traps where the CPU automatically pushes an error code.
 */ 
#define TRAPHANDLER(name, num)						\
.text		;\
	.globl name;		/* define global symbol for 'name' */	\
	.type name, @function;	/* symbol type is function */		\
	.align 2;		/* align function definition */		\
	name:			/* function starts here */		\
	pushl $(num);							\
	jmp _alltraps				;\
		.data					;\
		.long num, name

/* Use TRAPHANDLER_NOEC for traps where the CPU doesn't push an error code.
 * It pushes a 0 in place of the error code, so the trap frame has the same
 * format in either case.
 */
#define TRAPHANDLER_NOEC(name, num)					\
.text							;\
	.globl name;							\
	.type name, @function;						\
	.align 2;							\
	name:								\
	pushl $0;							\
	pushl $(num);							\
	jmp _alltraps				;\
		.data					;\
		.long num,name
		
#define TRAPHANDLER_syscall(name, num)					\
.text							;\
	.globl name;							\
	.type name, @function;						\
	.align 2;							\
	name:								\
	pushl $0;							\
	pushl $(num);							\
	jmp _syscalls				;\
		.data					;\
		.long num,name
		
.data
		.globl entry
entry:	

/*
 * Lab 3: Your code here for generating entry points for the different traps.
 */
TRAPHANDLER_NOEC(_divide,T_DIVIDE)
TRAPHANDLER_NOEC(_debug,T_DEBUG)
TRAPHANDLER_NOEC(_nmi,T_NMI )
TRAPHANDLER_NOEC(_brkpt,T_BRKPT)
TRAPHANDLER_NOEC(_oflow,T_OFLOW )
TRAPHANDLER_NOEC(_bound,T_BOUND)
TRAPHANDLER_NOEC(_illop,T_ILLOP)
TRAPHANDLER(_dblflt,T_DBLFLT)
TRAPHANDLER(_tss,T_TSS)
TRAPHANDLER(_segnp,T_SEGNP)
TRAPHANDLER(_stack,T_STACK)
TRAPHANDLER(_gpflt,T_GPFLT)
TRAPHANDLER(_pgflt,T_PGFLT)
TRAPHANDLER_NOEC(_fperr,T_FPERR)
TRAPHANDLER(_align,T_ALIGN)
TRAPHANDLER_NOEC(_mchk,T_MCHK)
TRAPHANDLER_NOEC(_simderr,T_SIMDERR)

TRAPHANDLER_syscall(_syscall,T_SYSCALL)
TRAPHANDLER_NOEC(_default,T_DEFAULT)

TRAPHANDLER_NOEC(_irqtimmer,IRQ_OFFSET+IRQ_TIMER)
TRAPHANDLER_NOEC(_irqkbd,IRQ_OFFSET+IRQ_KBD)
TRAPHANDLER_NOEC(_irqslave,IRQ_OFFSET+IRQ_SLAVE)
TRAPHANDLER_NOEC(_irqide,IRQ_OFFSET+IRQ_IDE)
TRAPHANDLER_NOEC(_irqerror,IRQ_OFFSET+IRQ_ERROR)
TRAPHANDLER_NOEC(_irqspurious,IRQ_OFFSET+IRQ_SPURIOUS)
TRAPHANDLER_NOEC(_irqserial,IRQ_OFFSET+IRQ_SERIAL)

/*
 * Lab 3: Your code here for _alltraps
 */
.data
		.long 0,0

.text
.func _alltraps
_alltraps:
		#step1
		pushl %ds				
		pushl %es				
		pushal					
		#step2
		movl $GD_KD, %eax		
		movw %ax, %ds			
		movw %ax, %es			
		#step3
		pushl %esp				
		#step4
		call trap				
		popl %esp				
		popal					
		popl %es				
		popl %ds				
		iret	
.endfunc
.text
.func _syscalls
_syscalls:
		#step1
		pushl %eax
		pushl %esi
		pushl %edi
		pushl %ebx
		pushl %ecx
		pushl %edx	
		#step2
		movl $GD_KD, %ebx		
		movw %bx, %ds			
		movw %bx, %es			
		#step3		
		#step4
		movl sysentry, %ebx
		call *(%ebx, %eax, 4)						
		popl %edx
		popl %ecx
		popl %ebx
		popl %edi
		popl %esi
		movl %eax, (%esp)								
		iret
.endfunc					
.data
		.globl sysentry
sysentry:		
		.long system_call_table